from zope.component import queryUtility
from plone.registry.interfaces import IRegistry
from five import grok
from interfaces import IShortUrl, IUrlSettingsUtility, IShortUrlAdapter, IUrlSettings
from zope.component import getAdapter
from zope.component import getUtility
from Products.CMFCore.interfaces import IContentish
from zope.annotation.interfaces import IAnnotations
from events import AddedShortUrlEvent
from zope.event import notify

class UrlSettingsUtility(grok.GlobalUtility):
    """
    This global utility is a conveniance utility to access
    settings in the Control Panel configlet and increment the
    short url codes, which are in turn assigned to objects.
    """
    grok.provides(IUrlSettingsUtility)
    grok.name('url-settings')
    URL_SEQUENCE = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789'
    
    def incrementSeed(self, seed):
        """
        This method takes the old seed value, or short url
        code value, and increments it returning a new seed.
        """
        if not seed:
            return self.URL_SEQUENCE[0]
        elif seed[-1] == self.URL_SEQUENCE[-1]:
            return unicode(self.incrementSeed(seed[0:-1]) + self.URL_SEQUENCE[0])
        else:
            return unicode(seed[0:-1] + self.URL_SEQUENCE[self.URL_SEQUENCE.find(seed[-1]) + 1])
    
    def getNewSeed(self):
        """
        This returns the current seed value and increments the
        seed in the control panel.
        """
        registry = queryUtility(IRegistry)
        
        seed = registry.records['ownio.url.interfaces.IUrlSettings.seed'].value
        registry['ownio.url.interfaces.IUrlSettings.seed'] = self.incrementSeed(seed)
        return seed
        
    def getContentTypes(self):
        """
        Returns a dictionary[content-type:remote-url-method] of the content types to be made
        short urls.
        """
        registry = queryUtility(IRegistry)
        if not registry: return {}

        types = {}
        for line in registry.records['ownio.url.interfaces.IUrlSettings.shortUrlContent'].value:
            key, value = [v.strip() for v in line.split('|')]
            types[key] = value
        return types
    
    @property
    def domain(self):
        """
        Returns the domain that hosts the short url codes.
        """
        registry = queryUtility(IRegistry)
        
        return registry.records['ownio.url.interfaces.IUrlSettings.domain'].value

class ShortUrlAdapter(grok.Adapter):
    """
    This is an adapter for content that provides the
    IShortUrl interface. It is meant to contain the 
    annotated field values for the item.
    """
    grok.provides(IShortUrlAdapter)
    grok.context(IShortUrl)
    grok.name("short-url-adapter")
    def __init__(self, context):
        """
        Initialization method.
        """
        self.context = context
        self.annotations = IAnnotations(context)
        if not self.isInitialized():
            self.initAnnotations()
    
    def isInitialized(self):
        """
        This checks if the content object has been
        annotated.
        """
        return self.annotations.has_key('short-url')
    
    def updateUrl(self):
        """
        Updates the remote url annotation value if the
        object was modified.
        """
        UrlSettingsUtility = getUtility(IUrlSettingsUtility, name='url-settings')
        urlMethod = getattr(self.context, UrlSettingsUtility.getContentTypes()[self.context.portal_type])
        if getattr(urlMethod, '__call__'):
            self.annotations['remote-url'] = urlMethod()
        else:
            self.annotations['remote-url'] = urlMethod
    
    def initAnnotations(self):
        """
        Initialize annotations. This is called the first time the
        adapter is invoked.
        """
        if self.isInitialized(): return
        UrlSettingsUtility = getUtility(IUrlSettingsUtility, name='url-settings')
        urlMethod = getattr(self.context, UrlSettingsUtility.getContentTypes()[self.context.portal_type])
        self.annotations['short-url'] = UrlSettingsUtility.getNewSeed()
        if getattr(urlMethod, '__call__'):
            self.annotations['remote-url'] = urlMethod()
        else:
            self.annotations['remote-url'] = urlMethod
        print self.shortUrl
        notify(AddedShortUrlEvent(self.context))
    
    @property
    def shortCode(self):
        """
        Returns the short url code. To get the short
        URL, use shortUrl.
        """
        return self.annotations['short-url']
    
    @property
    def remoteUrl(self):
        """
        Returns the remote url to which the short
        url points.
        """
        return self.annotations['remote-url']
    
    @property
    def shortUrl(self):
        """
        Returns the short url, based on the domain
        specified in the control panel.
        """
        UrlSettingsUtility = getUtility(IUrlSettingsUtility, name='url-settings')
        return '/'.join((UrlSettingsUtility.domain, self.annotations['short-url']))
